from django.shortcuts import render, redirect
from .models import FinancialStatement, FinancialHealthIndex
from .forms import FinancialStatementForm
from .utils import calculate_health_index_with_dynamic_weights, calculate_debt_risk, dynamic_weighted_debt_risk, \
    calculate_health_index
import matplotlib.pyplot as plt
from io import BytesIO
import base64
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error
from django.urls import reverse


# 动态权重计算函数
def dynamic_weights(industry, company_size):
    """
    动态计算财务健康指数各项比率的权重
    :param industry: 行业类型（例如：'tech'、'manufacturing'等）
    :param company_size: 企业规模（例如：'large'、'small'等）
    :return: 权重字典
    """
    if industry == 'tech':
        profitability_weight = 0.4
        solvency_weight = 0.3
        efficiency_weight = 0.3
    elif industry == 'manufacturing':
        profitability_weight = 0.3
        solvency_weight = 0.4
        efficiency_weight = 0.3
    else:
        profitability_weight = 0.3
        solvency_weight = 0.3
        efficiency_weight = 0.4

    # 根据公司规模调整权重
    if company_size == 'large':
        profitability_weight *= 1.1  # 大公司更注重盈利能力
        solvency_weight *= 1.1  # 大公司更注重偿债能力
    elif company_size == 'small':
        efficiency_weight *= 1.1  # 小公司更注重效率

    # 确保权重之和为1
    total_weight = profitability_weight + solvency_weight + efficiency_weight
    profitability_weight /= total_weight
    solvency_weight /= total_weight
    efficiency_weight /= total_weight

    return {
        'profitability': profitability_weight,
        'solvency': solvency_weight,
        'efficiency': efficiency_weight
    }


# 使用动态权重的健康指数计算


# Django视图：首页
def index(request):
    latest_statements = FinancialStatement.objects.all().order_by('-year')[:5]
    health_indices = FinancialHealthIndex.objects.all().order_by('-id')[:5]

    return render(request, 'index.html', {
        'latest_statements': latest_statements,
        'health_indices': health_indices,
    })


# Django视图：财务数据可视化
def visualization(request):
    years = ['2024', '2023', '2022', '2021', '2020']
    total_assets = [500000000, 450000000, 400000000, 380000000, 350000000]
    liabilities = [200000000, 180000000, 150000000, 140000000, 130000000]
    net_profit = [50000000, 45000000, 40000000, 35000000, 30000000]

    fig, ax = plt.subplots(figsize=(8, 6))
    ax.set_title('财务数据可视化分析')
    ax.set_xlabel('年度')
    ax.set_ylabel('金额（元）')
    ax.plot(years, total_assets, label='总资产', marker='o', linestyle='-', color='b')
    ax.plot(years, liabilities, label='负债', marker='o', linestyle='--', color='r')
    ax.plot(years, net_profit, label='净利润', marker='o', linestyle='-.', color='g')
    ax.legend()

    img_io = BytesIO()
    plt.savefig(img_io, format='png')
    img_io.seek(0)
    img_base64 = base64.b64encode(img_io.getvalue()).decode('utf-8')

    return render(request, 'visualization.html', {'chart': img_base64})


# Django视图：财务报表提交
def financials(request):
    if request.method == 'POST':
        form = FinancialStatementForm(request.POST)
        if form.is_valid():
            form.save()
            # 自动计算财务健康指数
            statement = form.save()
            # 假设行业为'tech'，企业规模为'large'
            health_index = calculate_health_index_with_dynamic_weights(statement, industry='tech', company_size='large')
            FinancialHealthIndex.objects.create(
                statement=statement,
                profitability_index=health_index['profitability_index'],
                solvency_index=health_index['solvency_index'],
                efficiency_index=health_index['efficiency_index'],
                overall_health_index=health_index['overall_health_index']
            )
            return redirect('index')
    else:
        form = FinancialStatementForm()
    return render(request, 'financials.html', {'form': form})


# Django视图：财务健康指数计算
def health_index(request):
    # 自定义财务报表数据（可以根据实际情况动态获取）
    statement = {
        'year': 2023,
        'total_assets': 500000000,
        'total_liabilities': 200000000,
        'equity': 300000000,
        'revenue': 150000000,
        'net_profit': 50000000,
        'operating_cash_flow': 40000000
    }

    # 假设行业为'tech'，企业规模为'large'
    health_index = calculate_health_index_with_dynamic_weights(statement, industry='tech', company_size='large')

    return render(request, 'health_index.html', {'statement': statement, 'health_index': health_index})


# 机器学习部分：训练模型（假设已有财务数据）
def train_financial_health_model():
    # 假设已经从数据库中提取了财务报表数据
    data = pd.DataFrame({
        'total_assets': [500000000, 450000000, 400000000, 380000000, 350000000],
        'total_liabilities': [200000000, 180000000, 150000000, 140000000, 130000000],
        'net_profit': [50000000, 45000000, 40000000, 35000000, 30000000],
        'revenue': [150000000, 130000000, 120000000, 110000000, 100000000],
        'overall_health_index': [78.2, 75.3, 72.6, 70.0, 68.1]
    })

    X = data[['total_assets', 'total_liabilities', 'net_profit', 'revenue']]
    y = data['overall_health_index']

    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

    model = RandomForestRegressor(n_estimators=100, random_state=42)
    model.fit(X_train, y_train)

    y_pred = model.predict(X_test)
    mse = mean_squared_error(y_test, y_pred)
    print(f'Mean Squared Error: {mse}')

    return model


def debt_risk_analysis(request):
    # 获取财务报表数据
    statement = {
        'total_liabilities': 200000000,
        'total_assets': 500000000,
        'revenue': 100000000,
        'operating_cash_flow': 20000000
    }

    # 计算负债风险
    debt_risk = calculate_debt_risk(statement)
    # 动态调整负债风险（假设行业为制造业）
    dynamic_risk = dynamic_weighted_debt_risk(statement, 'Manufacturing')

    return render(request, 'debt_risk_analysis.html', {
        'debt_risk': debt_risk,
        'dynamic_risk': dynamic_risk
    })


def financial_analysis(request, statement_id):
    # 获取指定的财务报表
    statement = FinancialStatement.objects.get(id=statement_id)

    # 使用已有的calculate_health_index函数进行财务健康分析
    health_index = calculate_health_index(statement)

    # 创建一个柱状图展示财务指标
    labels = ['盈利能力', '偿债能力', '效率']
    values = [health_index['profitability_index'], health_index['solvency_index'], health_index['efficiency_index']]

    fig, ax = plt.subplots(figsize=(8, 6))
    ax.bar(labels, values, color=['green', 'blue', 'orange'])
    ax.set_title('财务健康指标分析')
    ax.set_ylabel('百分比')

    # 将图形保存为图片并转化为 base64 格式
    img_io = BytesIO()
    plt.savefig(img_io, format='png')
    img_io.seek(0)
    img_base64 = base64.b64encode(img_io.getvalue()).decode('utf-8')

    # 渲染模板并传递数据
    return render(request, 'financial_analysis.html', {
        'statement': statement,
        'health_index': health_index,
        'chart': img_base64
    })


from decimal import Decimal

DEFAULT_STATEMENT = {
    'year': 2024,
    'total_assets': Decimal('500000000'),  # 使用 Decimal 类型
    'total_liabilities': Decimal('200000000'),  # 使用 Decimal 类型
    'equity': Decimal('300000000'),  # 使用 Decimal 类型
    'revenue': Decimal('100000000'),  # 使用 Decimal 类型
    'net_profit': Decimal('5000000'),  # 使用 Decimal 类型
    'operating_cash_flow': Decimal('20000000')  # 使用 Decimal 类型
}


def calculate_health_index01(statement):
    """
    计算财务健康指数
    :param statement: 财务报表数据（可以是字典或Django模型实例）
    :return: 健康指数字典
    """
    # 判断传入的 statement 是否为字典或模型实例，并根据类型进行处理
    if isinstance(statement, dict):
        # 如果是字典（即默认数据）
        net_profit = Decimal(statement['net_profit'])
        revenue = Decimal(statement['revenue'])
        total_assets = Decimal(statement['total_assets'])
        total_liabilities = Decimal(statement['total_liabilities'])
    else:
        # 如果是模型实例
        net_profit = Decimal(statement.net_profit)
        revenue = Decimal(statement.revenue)
        total_assets = Decimal(statement.total_assets)
        total_liabilities = Decimal(statement.total_liabilities)

    # 防止除数为零
    if revenue == 0:
        profitability = Decimal('0')
    else:
        profitability = (net_profit / revenue) * Decimal('100')  # 净利润与收入比率

    if total_liabilities == 0:
        solvency = Decimal('0')
    else:
        solvency = (total_assets / total_liabilities) * Decimal('100')  # 总资产与负债比率

    if total_assets == 0:
        efficiency = Decimal('0')
    else:
        efficiency = (net_profit / total_assets) * Decimal('100')  # 净利润与总资产比率

    # 对指数进行归一化或加权平均
    overall_health = (profitability * Decimal('0.3') + solvency * Decimal('0.4') + efficiency * Decimal('0.3'))

    # 返回健康指数字典
    return {
        'profitability_index': round(profitability, 2),
        'solvency_index': round(solvency, 2),
        'efficiency_index': round(efficiency, 2),
        'overall_health_index': round(overall_health, 2)
    }


def financial_data_analysis(request, statement_id):
    try:
        # 尝试获取指定的财务报表数据
        statement = FinancialStatement.objects.get(id=statement_id)
    except FinancialStatement.DoesNotExist:
        # 如果没有找到数据，则使用默认数据
        statement = DEFAULT_STATEMENT

    # 使用 calculate_health_index 计算健康指数
    health_index = calculate_health_index01(statement)

    # 生成财务数据分析图
    if isinstance(statement, dict):  # 如果是字典（即使用默认数据）
        years = [str(statement['year'] - i) for i in range(5)]  # 使用字典中的数据
        total_assets = [statement['total_assets'], statement['total_assets'] * Decimal('0.9'),
                        statement['total_assets'] * Decimal('0.8'), statement['total_assets'] * Decimal('0.7'),
                        statement['total_assets'] * Decimal('0.6')]
        liabilities = [statement['total_liabilities'], statement['total_liabilities'] * Decimal('0.9'),
                       statement['total_liabilities'] * Decimal('0.8'), statement['total_liabilities'] * Decimal('0.75'),
                       statement['total_liabilities'] * Decimal('0.65')]
    else:  # 如果是模型实例
        years = [str(statement.year - i) for i in range(5)]
        total_assets = [statement.total_assets, statement.total_assets * Decimal('0.9'), statement.total_assets * Decimal('0.8'),
                        statement.total_assets * Decimal('0.7'), statement.total_assets * Decimal('0.6')]
        liabilities = [statement.total_liabilities, statement.total_liabilities * Decimal('0.9'),
                       statement.total_liabilities * Decimal('0.8'), statement.total_liabilities * Decimal('0.75'),
                       statement.total_liabilities * Decimal('0.65')]

    # 绘制财务数据趋势分析图
    fig, ax = plt.subplots(figsize=(10, 6))
    ax.plot(years, total_assets, label="总资产", marker='o', linestyle='-', color='blue')
    ax.plot(years, liabilities, label="负债", marker='o', linestyle='--', color='red')
    ax.set_xlabel('年度')
    ax.set_ylabel('金额（元）')
    ax.set_title('财务数据趋势分析')
    ax.legend()

    # 保存图表为图片并转化为base64格式
    img_io = BytesIO()
    plt.savefig(img_io, format='png')
    img_io.seek(0)
    img_base64 = base64.b64encode(img_io.getvalue()).decode('utf-8')

    # 业务简介和创出分析
    business_overview = "根据最新财务报表，企业的总资产持续增长，负债保持在合理水平，但收入增速放缓，净利润有所下降。"
    growth_analysis = "预计未来企业将重点改善盈利能力，增加现金流入，并优化资本结构以应对市场压力。"

    # 渲染模板并传递数据
    return render(request, 'financial_data_analysis.html', {
        'statement': statement,
        'health_index': health_index,
        'chart': img_base64,
        'business_overview': business_overview,
        'growth_analysis': growth_analysis,
    })


# 添加财务报表的视图
def add_financial_statement(request):
    if request.method == 'POST':
        form = FinancialStatementForm(request.POST)
        if form.is_valid():
            financial_statement = form.save()

            # 自动计算财务健康指数并保存
            health_index = calculate_health_index(financial_statement)
            FinancialHealthIndex.objects.create(
                statement=financial_statement,
                profitability_index=health_index['profitability_index'],
                solvency_index=health_index['solvency_index'],
                efficiency_index=health_index['efficiency_index'],
                overall_health_index=health_index['overall_health_index']
            )

            return redirect('financial_statement_list')  # 重定向到财务报表列表页面
    else:
        form = FinancialStatementForm()

    return render(request, 'add_financial_statement.html', {'form': form})


# 展示财务报表列表以及健康指数
def financial_statement_list(request):
    statements = FinancialStatement.objects.all()
    health_indices = FinancialHealthIndex.objects.all()

    return render(request, 'financial_statement_list.html', {
        'statements': statements,
        'health_indices': health_indices
    })
